﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Builders;

namespace Yamfinder.Data
{
    public class LexicalQuery : ILexicalQuery
    {
        private readonly ILexicalRepository _lexicalRepository;

        public LexicalQuery(ILexicalRepository lexicalRepository)
        {
            _lexicalRepository = lexicalRepository;
        }

        public IList<LexicalEntry> ExecuteFilters(IList<LexicalFilter> filters)
        {
            //if no filters just return entire database :/
            if (filters.Count <= 0)
            {
                return _lexicalRepository.Query(Query.Null);
            }

            //for now we shall just collect all the querys and AND them together
            var querys = new List<IMongoQuery>();

            foreach (var lexicalFilter in filters)
            {
                var fieldname = lexicalFilter.Fieldname;

                switch (lexicalFilter.Filter)
                {
                    case FilterType.GPSLocWithinRange:
                        break;
                    case FilterType.TextOnlyExactMatch: //Works
                        var stringMatchData = lexicalFilter.GetStringData("data");
                        querys.Add(Query.EQ(fieldname,BsonValue.Create(stringMatchData)));
                        break;
                    case FilterType.TextContains:
                        var stringContainsData = lexicalFilter.GetStringData("data");
                        querys.Add(Query.Matches(fieldname, stringContainsData + "/i"));
                        break;
                    case FilterType.TextStartsWith:
                        var stringStartsWithData = lexicalFilter.GetStringData("data");
                        querys.Add(Query.Matches(fieldname,"^" +stringStartsWithData + "/i"));
                        break;
                    case FilterType.TextEndsWith:
                        var stringEndsWithData = lexicalFilter.GetStringData("data");
                        querys.Add(Query.Matches(fieldname, "(?:" + stringEndsWithData + ")\\$/i"));
                        break;
                    case FilterType.TextRegExMatch:
                        var stringRegExData = lexicalFilter.GetStringData("data");
                        querys.Add(Query.Matches(fieldname, stringRegExData));
                        break;
                    case FilterType.IntegerIsEqualTo:
                        var integerIsEqualData = lexicalFilter.GetLongData("data");
                        //queryable = queryable.Where(x => ((long)))
                        break;
                    case FilterType.IntegerGreaterThan:
                        break;
                    case FilterType.IntegerGreaterThanOrEqualTo:
                        break;
                    case FilterType.IntegerLessThan:
                        break;
                    case FilterType.IntegerLessThanOrEqualTo:
                        break;
                    case FilterType.IntegerWithinRange:
                        break;
                    case FilterType.IntegerOutsideRange:
                        break;
                    case FilterType.DecimalIsEqualTo:
                        break;
                    case FilterType.DecimalGreaterThan:
                        break;
                    case FilterType.DecimalGreaterThanOrEqualTo:
                        break;
                    case FilterType.DecimalLessThan:
                        break;
                    case FilterType.DecimalLessThanOrEqualTo:
                        break;
                    case FilterType.DecimalWithinRange:
                        break;
                    case FilterType.DecimalOutsideRange:
                        break;
                    case FilterType.DateIsEqualTo:
                        break;
                    case FilterType.DateGreaterThan:
                        break;
                    case FilterType.DateGreaterThanOrEqualTo:
                        break;
                    case FilterType.DateLessThan:
                        break;
                    case FilterType.DateLessThanOrEqualTo:
                        break;
                    case FilterType.DateWithinRange:
                        break;
                    case FilterType.DateOutsideRange:
                        break;
                    default:
                        throw new ArgumentOutOfRangeException();
                }
            }

            var finalQuery =  Query.And(querys.ToArray());

            return _lexicalRepository.Query(finalQuery);
        }
    }
}
